/***************************************************************************
 *                                                                         *
 * Copyright (c) 2007 - 2009 Nuvoton Technology Corp. All rights reserved.*
 *                                                                         *
 ***************************************************************************/
 
/****************************************************************************
 * 
 * FILENAME
 *     NUC900_VPOST_OPT_NTSC.c
 *
 * VERSION
 *     0.1 
 *
 * DESCRIPTION
 *
 *
 *
 *
 * DATA STRUCTURES
 *     None
 *
 * FUNCTIONS
 *
 *
 *     
 * HISTORY
 *     2005.03.16		Created by Shih-Jen Lu
 *
 *
 * REMARK
 *     None
 *
 *
 **************************************************************************/
#include "wblib.h"
#include "NUC900_VPOST_Regs.h"
#include "NUC900_VPOST.h"
#ifdef	HAVE_OPT_NTSC

#ifdef ECOS
cyg_handle_t	vpost_int_handle;
cyg_interrupt	vpost_int_holder;
#endif

//static VPOST_T	_tOPT_NTSC;
static UINT32 g_nScreenWidth;
static UINT32 g_nScreenHeight;

static void Delay(int nCnt)
{
	volatile int  loop;
	for (loop=0; loop<nCnt; loop++);
}


static VOID vpostDisp_F_ISR(void)
{
    outpw(REG_LCM_INT_CS,inpw(REG_LCM_INT_CS) | VPOSTB_DISP_F_STATUS);
    vpostVAStartTrigger();
}
static VOID vpostUNDERRUN_ISR(void)
{
	outpw(REG_LCM_INT_CS,inpw(REG_LCM_INT_CS) | VPOSTB_UNDERRUN_INT);
}

static VOID vpostBUS_ERROR_ISR(void)
{
	outpw(REG_LCM_INT_CS,inpw(REG_LCM_INT_CS) | VPOSTB_BUS_ERROR_INT);
}
#ifdef ECOS
static cyg_uint32 vpostIntHandler(cyg_vector_t vector, cyg_addrword_t data)
#else
static VOID vpostIntHandler(void)
#endif
{
   /* clear VPOST interrupt state */
   UINT32 uintstatus;
   
   uintstatus = inpw(REG_LCM_INT_CS);
   if (uintstatus & VPOSTB_DISP_F_STATUS)  
      vpostDisp_F_ISR();
   else if (uintstatus & VPOSTB_UNDERRUN_INT)
      vpostUNDERRUN_ISR();
   else if (uintstatus & VPOSTB_BUS_ERROR_INT)
      vpostBUS_ERROR_ISR();

#ifdef ECOS
	return CYG_ISR_HANDLED;
#endif
}

static void vpostEnable_Int(void)
{
#ifdef ECOS
    cyg_interrupt_create(IRQ_LCD, 1, 0, vpostIntHandler, NULL, &_tOPT_NTSC.vpost_int_handle, &_tOPT_NTSC.vpost_int_holder);
    cyg_interrupt_attach(vpost_int_handle);
    cyg_interrupt_unmask(IRQ_LCD);
#else
    sysInstallISR(IRQ_LEVEL_1, IRQ_LCD, (PVOID)vpostIntHandler);
    /* enable VPOST interrupt */
    sysEnableInterrupt(IRQ_LCD);
#endif
    writew(REG_LCM_DCCS,readw(REG_LCM_DCCS) | VPOSTB_DISP_INT_EN);
    writew(REG_LCM_INT_CS,readw(REG_LCM_INT_CS) | VPOSTB_UNDERRUN_EN | VPOSTB_DISP_F_EN);
}



//INT vpostOSDInit_OPT_NTSC(UINT16 ucOSDSrcType,UINT16 usxstart,UINT16 usystart,
//											UINT16 usxend,UINT16 usyend,UINT16 usOSDPicWidth)
INT vpostOSDInit_OPT_NTSC(POSDFORMATEX pOSDformatex)
{

    vpostSetOSDSrc(pOSDformatex->ucOSDSrcFormat);
    
    vpostSetOSDBuffer(pOSDformatex->pFrameBuffer);
    /*if (ucOSDSrcType != 0)
     	writew(REG_LCM_DCCS,readw(REG_LCM_DCCS) | ucOSDSrcType);
     else
     	writew(REG_LCM_DCCS,readw(REG_LCM_DCCS) & 0xffff0fff);//clear OSD SRC setting	
	*/
	vpostOSDSetWindow(pOSDformatex->nXstart,pOSDformatex->nYstart,pOSDformatex->nOSDWidth,pOSDformatex->nOSDHeight);
     
	writew(REG_LCM_OSD_FBCTRL,0);//clear OSD STRIDE,FF setting
    if ((pOSDformatex->ucOSDSrcFormat==OSD_SRC_RGB888)||(pOSDformatex->ucOSDSrcFormat==OSD_SRC_RGB666)){
		writew(REG_LCM_OSD_FBCTRL,(pOSDformatex->nImageWidth<<16) | pOSDformatex->nImageWidth); //OSDFF~OSD_STRIDE
    }
    else if (pOSDformatex->ucOSDSrcFormat==OSD_SRC_RGB332)
    {
    	writew(REG_LCM_OSD_FBCTRL,((pOSDformatex->nImageWidth/4)<<16) | (pOSDformatex->nImageWidth/4)); //OSDFF~OSD_STRIDE
    }
    else{
        writew(REG_LCM_OSD_FBCTRL,((pOSDformatex->nImageWidth/2)<<16) | (pOSDformatex->nImageWidth/2)); //OSDFF~OSD_STRIDE
    }
    
    vpostOSDScalingCtrl(1,0,0);  // unmask by smf
    vpostOSDSetOverlay(DISPLAY_OSD,DISPLAY_OSD,0,0,0);  // add by smf
    
    return 0;
}








static VOID vpostSetCRTC_OPT_NTSC(UINT16 usHorizontal,UINT16 usVertical,UINT16 ucVASrcType,UINT16 usPicWidth)
{   
	
	outpw(REG_LCM_CRTC_SIZE,0x0106035a); //CRTC_SIZE
    outpw(REG_LCM_CRTC_DEND,0x00f202c7); //CRTC_DEND,242X711
    outpw(REG_LCM_CRTC_HR,0x02e002d8); //CRTC_HR
    outpw(REG_LCM_CRTC_HSYNC,0x034502d7); //CRTC_HSYNC
    outpw(REG_LCM_CRTC_VR,0x00fa00f4); //CRTC_VR
    if ((ucVASrcType==VA_SRC_RGB888) || (ucVASrcType==VA_SRC_RGB666))
    {
  		outpw(REG_LCM_VA_FBCTRL,inpw(REG_LCM_VA_FBCTRL) &~0x7ff07ff | (usPicWidth<<16) | usPicWidth); //VAFF~VA_STRIDE
	}
	else
	{
		outpw(REG_LCM_VA_FBCTRL,inpw(REG_LCM_VA_FBCTRL) &~0x7ff07ff | ((usPicWidth/2)<<16) | (usPicWidth/2)); //VAFF~VA_STRIDE
	}   
	    

}



//INT vpostLCMInit_OPT_NTSC(VA_CB_FUNC_T *fnCallBack,UINT16 ucVASrcType,UINT8 ucVADisMode,UINT16 usPicWidth,UINT8 ucROT90)
INT vpostLCMInit_OPT_NTSC(PLCDFORMATEX plcdformatex)
{
	/*
	_tOPT_NTSC.usDevWidth = 711;
	_tOPT_NTSC.usDevHeight = 484;
	_tOPT_NTSC.uCmdLow = 0;
	_tOPT_NTSC.ucCmd16t18 = 0;
	_tOPT_NTSC.uCmdBusWidth = 0;
	_tOPT_NTSC.uDataBusWidth = 0;
	_tOPT_NTSC.ucMPU_Mode = 0;
	_tOPT_NTSC.uMPU_ColorMode = VPOSTB_COLORTYPE_64K;
	_tOPT_NTSC.ucDeviceType = VPOSTB_DEVICE_SYNC_YUV422;
	_tOPT_NTSC.fnDisplayCallBack = fnCallBack;
	*/
	UINT32 VA_FF;
	UINT32 VA_Sride;
	UINT32 nBytesPixel;
	
	outpw(REG_MFSEL,inpw(REG_MFSEL) | (3<<2));
	outpw(REG_CLKEN,inpw(REG_CLKEN) | 0x1);
	
	outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | VPOSTB_ENG_RST);
	Delay(100);
	outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) & ~VPOSTB_ENG_RST);
	Delay(100);
	
	//g_nScreenWidth = plcdformatex->nScreenWidth = 711;
	g_nScreenWidth = plcdformatex->nScreenWidth = 720;
	g_nScreenHeight = plcdformatex->nScreenHeight = 484;
	
	if ( (plcdformatex->ucVASrcFormat == VA_SRC_RGB888) || (plcdformatex->ucVASrcFormat == VA_SRC_RGB666))//4 BytesPixel
	{
	    nBytesPixel = 4;
	}
	else
	{
	    nBytesPixel = 2;
	}
	plcdformatex->nFrameBufferSize = g_nScreenWidth*g_nScreenHeight*nBytesPixel;
	
	/* set the display buffer (fetch from VA_BADDR0, if at single buffer mode)*/
	if (vpostAllocVABuffer(plcdformatex,nBytesPixel)==FALSE)
		return ERR_NULL_BUF;
	
	/* set display mode */
	vpostSetDisplayMode(0);  // continue mode
	
	/* set display video source format */
	vpostSetVASrc(plcdformatex->ucVASrcFormat);
	/*
	if (ucVASrcType!=0)
		outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) | ucVASrcType);
	else
		outpw(REG_LCM_DCCS,inpw(REG_LCM_DCCS) & ~(7<<8));
	*/
	//18-bit,256k,80mode,mpu-based,cmd18-16L0
	
	
	//vpostSetDeviceCtrl(_tOPT_NTSC);
	//outpw(REG_LCM_DEV_CTRL,0xA1C00004);
	//outpw(REG_LCM_DEV_CTRL,0x02E00002);  // important information . mask by smf
	/*
	outpw(REG_LCM_DEV_CTRL,0xE0);//set default value
	writew(REG_LCM_DEV_CTRL,inpw(REG_LCM_DEV_CTRL) | _tOPT_NTSC.uCmdLow 
												   | _tOPT_NTSC.ucCmd16t18
												   | _tOPT_NTSC.uCmdBusWidth
												   | _tOPT_NTSC.uDataBusWidth
												   | _tOPT_NTSC.ucMPU_Mode
												   | _tOPT_NTSC.uMPU_Color_Mode
												   | _tOPT_NTSC.ucDeviceType );
	*/
	
	outpw(REG_LCM_DEV_CTRL,0x0); //clear register
	//outpw(REG_LCM_DEV_CTRL,0x02E00002);
	writew(REG_LCM_DEV_CTRL,inpw(REG_LCM_DEV_CTRL) | VPOSTB_VR_LACE
												   | VPOSTB_V_POL  
												//   | VPOSTB_SWAP_YUYV      // depend on FAL_D
												//   | VPOSTB_FAL_D );    // depend on SWAP_YUYV
												//| VPOSTB_LACE         
												   | VPOSTB_COLORTYPE_64K );
	
	vpostSetCRTC_OPT_NTSC(g_nScreenWidth, g_nScreenHeight,
						plcdformatex->ucVASrcFormat, g_nScreenWidth);
	
	/* set video stream frame buffer control */
	VA_FF = (plcdformatex->nScreenWidth)*(nBytesPixel)/4;//word unit
    VA_Sride = (plcdformatex->nScreenWidth)*(nBytesPixel)/4;//word unit
    outpw(REG_LCM_VA_FBCTRL,inpw(REG_LCM_VA_FBCTRL) &~0x7ff07ff | (VA_FF<<16) | VA_Sride);
						
	//vpostEnable_Int();
	vpostVAScalingCtrl(1,0,1,0,VA_SCALE_INTERPOLATION);
	vpostVAStartTrigger();   // add by smf
	
	return 0;
}



#endif	/* HAVE_SAMSUNG_80_18IT */